// @Author EthanScriptOn
// @Desc
package log_worker

import (
	"gitee.com/fatzeng/srf_switch_basic_components/pool"
	"gitee.com/fatzeng/srf_switch_basic_components/queue"
	"gitee.com/fatzeng/srf_switch_basic_components/util"
	"gitee.com/fatzeng/srf_switch_log/log_define"
	log2 "gitee.com/fatzeng/srf_switch_log/log_task"
	"gitee.com/fatzeng/srf_switch_protocol/protocol/log"
	"io"
	"os"
	"sync"
)

type LoggerExporterWorker struct {
	*pool.DefaultWorker
	wc   io.WriteCloser
	send sync.Once
}

func GenerateLoggerExporterWorker(queue queue.Queue, weight int) *LoggerExporterWorker {
	return &LoggerExporterWorker{
		DefaultWorker: pool.GenerateDefaultWorker(queue, weight),
	}
}

func (l *LoggerExporterWorker) BuildOutputStream(outPutPath string, outPutType log_define.OutPutType) (err error) {
	defer util.HandleErr(&err)
	var outStream io.WriteCloser
	switch outPutType {
	case log_define.CONSOLE:
		outStream = os.Stdout
	case log_define.FILE:
		file, openFileErr := os.OpenFile(outPutPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
		if openFileErr != nil {
			err = openFileErr
			return err
		}
		outStream = file
	}
	l.wc = outStream
	return
}

func (l *LoggerExporterWorker) SendOption(pool.Task) error {
	l.send.Do(func() {
		// As the output layer of the log, the queue consumes instead of writing tasks directly,
		// so that the load of the queue participates in the calculation of the pool
		go func() {
			for pullMsg, err := l.GetQueue().Pull(); ; {
				if err != nil {
					log.Logger().Error("LoggerExporterWorker Send task error %v", err)
				}
				unitTask, ok := pullMsg.(*log2.LogUnitTask)
				if !ok {
					log.Logger().Error("LoggerExporterWorker Send task error task is %v", pullMsg)
					return
				}
				outPutStr := unitTask.GetFormatStr()
				if err = l.BuildOutputStream(unitTask.GetRule().OutPutPath, unitTask.GetRule().OutPutType); err != nil {
					log.Logger().Error("LoggerExporterWorker Send task error err is %v", err)
					return
				}
				if _, err = l.wc.Write([]byte(outPutStr)); err != nil {
					log.Logger().Error("LoggerExporterWorker Send task error err is %v", err)
				}
			}
		}()
	})
	return nil
}
